/******************************************************************************
 * @File name   :      SmContentServiceImpl.java
 *
 * @Author      :      chen shixiang
 *
 * @Date        :      2011-7-7
 *
 * @Copyright Notice: 
 * Copyright (c) 2011 SGM, Inc. All  Rights Reserved.
 * This software is published under the terms of the SGM Software
 * License version 1.0, a copy of which has been included with this
 * distribution in the LICENSE.txt file.
 * 
 * 
 * ----------------------------------------------------------------------------
 * Date                   Who         Version        Comments
 * 2011-7-7 下午02:29:36        chen shixiang     1.0            Initial Version
 * 2011-9-23 下午06:02:22         Wu Jianxi       1.1         add method generateSmsContent implementation
 * 2011-9-27 上午09:42:44         Wu Jianxi       1.2         add method createSmsContent
 * 2011-10-28 上午09:39:31        HeHao           1.3         Create Message
 * 2011-11-3 下午02:04:38         Wu Jianxi       1.4         fix dead loop bug
 *****************************************************************************/
package com.cap.bts.framework.sms.service.impl;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrSubstitutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cap.bts.commonfunc.common.constant.BusinessTypeConstants;
import com.cap.bts.commonfunc.common.constant.SmSendStatus;
import com.cap.bts.commonfunc.common.constant.SmsContentConstants;
import com.cap.bts.commonfunc.common.constant.errorcode.GEErrorCodes;
import com.cap.bts.commonfunc.common.dto.SmsContentDetailDto;
import com.cap.bts.commonfunc.common.service.ISmsService;
import com.cap.bts.commonfunc.sms.constant.SmsTemplateConstants;
import com.cap.bts.commonfunc.sms.dao.IShortMessageTemplateDao;
import com.cap.bts.commonfunc.sms.dao.ISmContentDao;
import com.cap.bts.commonfunc.sms.domain.SmContent;
import com.cap.bts.commonfunc.sms.domain.SmsTemplate;
import com.cap.bts.commonfunc.sms.dto.SmsContentResultDto;
import com.cap.bts.commonfunc.sms.dto.SmsStatus;
import com.cap.bts.commonfunc.sms.service.IShortMessageTemplateService;
import com.cap.bts.framework.common.exception.AppException;
import com.cap.bts.framework.common.service.impl.BaseServiceImpl;
import com.cap.bts.framework.common.util.Utils;
import com.cap.bts.framework.paramgnt.service.ISystemParaManagement;
import com.cap.bts.framework.sms.constant.HttpSMSConstant;
import com.cap.bts.framework.sms.constant.SMSConstants;
import com.cap.bts.framework.sms.dto.SMSTextMessage;
import com.cap.bts.framework.sms.dto.TextMessage;
import com.cap.bts.framework.sms.service.IMessageSender;
import com.cap.bts.framework.sms.service.ISmContentService;
import com.cap.bts.framework.sms.util.HttpSMSProcessUtil;

/**
 *
 */
@Transactional(rollbackFor = AppException.class)
@Service("smContentService")
public class SmContentServiceImpl extends BaseServiceImpl implements
		ISmContentService {

	@Resource(name = "smsContentDao")
	private ISmContentDao smContentDao;

	@Resource(name = "shortMessageTemplateServiceImpl")
	private IShortMessageTemplateService smsTemplateService;

	@Autowired
	private ISmsService smsService;
	
	
	@Autowired
	private ISystemParaManagement systemParaManagement;
	
    @Autowired
    private IShortMessageTemplateDao msgTemplateDao;

	/**
	 * {@inheritDoc} overridden:
	 * 
	 * @Date : 2011-7-7
	 * @see com.cap.bts.doss.sms.service.ISmContentService#sendMessage()
	 **/
	@Override
	public void sendMessage() throws AppException {
		try {
			IMessageSender messageSender = new MessageSenderImpl();
			List<SmContent> listSm = null;
			int index;
			// do send sms before loop
			do {
				listSm = smContentDao.findSmContentBySentStatus();
				index = 0;// reset to zero
				// if there is no sms to be sent,just break this loop.
				if (null == listSm || listSm.size() == 0) {
					return;
				}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				
				// loop for send sms and update sms content's has_sent flag to sent
				for (SmContent smContent : listSm) {

					/**
					 * 以下临时关闭：交车短信，订单短信，试乘试驾短信
					 */
					if (smContent.getBussinessType() != null) {
						if (smContent.getBussinessType() == BusinessTypeConstants.ORDER_THANKS
								|| smContent.getBussinessType() == BusinessTypeConstants.DELIVERY_THANKS
								|| smContent.getBussinessType() == BusinessTypeConstants.TEST_DRIVING) {
							
							smContent.setHasSent(SmSendStatus.SENT.getValue());
							smsService.update(smContent);
							continue;
						}
					}
					/**
					 * 以上临时关闭：交车短信，订单短信，试乘试驾短信
					 */
					TextMessage tm = new TextMessage();
					int productId = getSmsProductId(smContent.getBussinessType());
					tm.setProductId(productId);
					tm.setContent(smContent.getContent());
					tm.setMessagePriority(SMSConstants.MESSAGE_PRIORITY_HIGHEST);
					tm.setMobile(String.valueOf(smContent.getDestmobile()));
					try {
						index ++;
						messageSender.sendMessage(tm);
						if(index >= 500){//sleep 0.5s for each 500 times of loop
							try {
								Thread.sleep(500);
							} catch (InterruptedException e1) {
								e1.printStackTrace();
							}
							index = 0;
						}

						smContent.setHasSent(SmSendStatus.SENT.getValue());
						smsService.update(smContent);
					} catch (Exception e) {
					    System.out.println("The stupid SMS platform cannot be connected!!!! " + e.getLocalizedMessage());
					    try {
                            Thread.sleep(60000);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
						// in next loop this sms content will be sent again,so don't
						// throw this exception;
					} finally {
						smContentDao.clear();
					}
				}

				// clear entity manager's 1st level cache, avoid out of memory
				// exception.
				// smContentDao.clear();

				// 如果本次循环，已查询所有的未发送短信，则跳出循环，等待下次定时程序启动
				if (SmsContentConstants.SMS_SEND_BATCH_SIZE > listSm.size()) {
					break;
				}

			} while (SmsContentConstants.SMS_SEND_BATCH_SIZE == listSm.size());
		} catch (Exception e) {
			e.printStackTrace();
			throw new AppException("sendMessage(SMS) failed.",e.getLocalizedMessage());
		} finally {
			smContentDao.clear();
		}

	}

	/**
	 * {@inheritDoc} overridden:
	 * 
	 * @Date : 2011-9-20
	 * @see com.cap.bts.commonfunc.common.service.ISmContentService#createSmsContent(com.cap.bts.commonfunc.common.domain.SmContent)
	 **/
	@Override
	public  SmContent  createSmsContent(SmContent smsContent) throws AppException {
	  return smContentDao.save(smsContent);
	}

	/**
	 * {@inheritDoc} overridden:
	 * 
	 * @Date : 2011-9-20
	 * @see com.cap.bts.commonfunc.common.service.ISmContentService#deleteSmsContent(int)
	 **/
	@Override
	public void deleteSmsContent(int businessType, long businessItemId)
			throws AppException {
		smContentDao.deleteSmsContent(businessType, businessItemId);
	}

	/**
	 * 
	 * @Date : 2011-12-8
	 * @param businessType
	 * @return
	 */
	private int getSmsProductId(int businessType) {
		int productId = SmsContentConstants.COMMON_PRODUCT_ID;
		switch (businessType) {

		case SmsContentConstants.BUSINESS_TYPE_ORDER_FEEDBACK:
			productId = SmsContentConstants.PRODUCT_ID_ORDER_FEEDBACK;
			break;
		case SmsContentConstants.BUSINESS_TYPE_FOLLOW_UP_FEEDBACK:
			productId = SmsContentConstants.PRODUCT_ID_FOLLOW_UP_FEEDBACK;
			break;
		case SmsContentConstants.BUSINESS_TYPE_TEST_DRIVING_FEEDBACK:
			productId = SmsContentConstants.PRODUCT_ID_TEST_DRIVING_FEEDBACK;
			break;
		default:
			productId = SmsContentConstants.COMMON_PRODUCT_ID;
		}

		return productId;
	}

	/**
	 * {@inheritDoc} overridden:
	 * 
	 * @Date : 2011-9-26
	 * @see com.cap.bts.commonfunc.common.service.ISmContentService#sendSmsContent(com.cap.bts.commonfunc.common.dto.SmsContentDetailDto)
	 **/
	@Override
	public SmContent createSmsContent(SmsContentDetailDto dto) throws AppException {
        List<SmsTemplate> smsTemplates = msgTemplateDao.findTemplateByTemplateCode(dto.getTemplateNo());
        // NULL CHECK
        if (null == smsTemplates || smsTemplates.isEmpty()) {
            throw new AppException(GEErrorCodes.GE_SMS_TEMPLATE_NOT_FOUND,
                    "Sms Template is NOT Found.");
        }else{
            SmsTemplate smsTemplate = smsTemplates.get(0);
            if(smsTemplate == null){
                throw new AppException(GEErrorCodes.GE_SMS_TEMPLATE_NOT_FOUND,
                "Sms Template is NOT Found.");
            }
            String content = generateSmsContent(smsTemplate, dto.getParaMap());

            // 短信内容为空提醒用户
            if (Utils.isNullOrEmpty(content)) {
                logger.info("Sms Content is Empty.");
                throw new AppException(GEErrorCodes.GE_SMS_CONTENT_EMPTY,
                        "Sms Content is Empty.");
            }

            SmContent smsContent = new SmContent();
            smsContent.setBusinessItemId(dto.getBusinessItemId());
            smsContent.setBussinessType(dto.getBusinessType());
            smsContent.setContent(content);
            // 如果手机号码不存在
            if (null == dto.getDestMobile()) {
                throw new AppException(
                        GEErrorCodes.GE_SMS_DEST_MOBILE_NOT_EXISTS,
                        "SMS SendTo Mobile does NOT Exist.");
            }
            smsContent.setDestmobile(dto.getDestMobile());
            smsContent.setHasSent(SmSendStatus.SENT.getValue());
            SmContent smContent=this.createSmsContent(smsContent);
            SMSTextMessage textMessage = new SMSTextMessage();
            textMessage.setContent(content);
            textMessage.setMobile(String.valueOf(dto.getDestMobile()));
            String isSendMessage = systemParaManagement.getSysParameter("PREFIX_SMS_SETTING", "IS_SEND_MESSAGE");
            if(Utils.notEmpty(isSendMessage) && isSendMessage.equals(HttpSMSConstant.SEND_MESSAGE_TRUE)){
                String resultMsg = HttpSMSProcessUtil.sendMessage(textMessage);
                
                smContent.setMsgId(resultMsg);
                
                if(org.apache.commons.lang3.StringUtils.startsWith(resultMsg, "-")){
//                if(!sendSuccess){
                   // smContentDao.findById(smContent.getId()).setHasSent(0);
                    //throw new AppException("Exception: Failed to send SMS","Exception: Failed to send SMS");
                }
            }
            return smContent;
        }
        
        
    }

	/**
	 * 
	 * @Date : 2011-9-27
	 * @param smsTemplate
	 * @param paraMap
	 * @return
	 */
	@Override
	public String generateSmsContent(SmsTemplate smsTemplate,
			Map<String, String> paraMap) throws AppException  {
		if (null != smsTemplate) {
			StrSubstitutor substitutor = new StrSubstitutor(paraMap,
					SmsTemplateConstants.SMS_VARIABLE_PREFIX,
					SmsTemplateConstants.SMS_VARIABLE_SUFFIX);
			return substitutor.replace(smsTemplate.getMessageContent());
		}
		return "";
	}

	/**
	 * {@inheritDoc} overridden:
	 * 
	 * @Date : 2011-12-28
	 * @see com.cap.bts.commonfunc.common.service.ISmContentService#generateSmsContent(com.cap.bts.commonfunc.common.dto.SmsContentDetailDto)
	 **/
	@Override
	public SmsContentResultDto generateSmsContent(SmsContentDetailDto dto)
			throws AppException {
		SmsTemplate smsTemplate = smsTemplateService.getSmsTemplate(
				dto.getBrandId(), dto.getDealerId(), dto.getNotificationDate(),
				dto.getTemplateNo());

		// NULL CHECK
		if (null == smsTemplate) {
			logger.info("SmsTemplate With [templateNo=" + dto.getTemplateNo()
					+ "] is null.");
			throw new AppException(GEErrorCodes.GE_SMS_TEMPLATE_NOT_FOUND,
					"Sms Template is NOT Found.");
		}

		String content = generateSmsContent(smsTemplate, dto.getParaMap());

		// 短信内容为空提醒用户
		if (StringUtils.isBlank(content)) {
			logger.info("Sms Content is Empty.");
			throw new AppException(GEErrorCodes.GE_SMS_CONTENT_EMPTY,
					"Sms Content is Empty.");
		}
		SmsContentResultDto resultDto = new SmsContentResultDto();
		resultDto.setContent(content);
		resultDto.setSmsTemplate(smsTemplate);

		return resultDto;
	}

	@Override
	public void batchInsertStatus(List<SmsStatus> dataList) throws AppException{
		if(dataList != null && !dataList.isEmpty()){
			smContentDao.batchInsertStatus(dataList);
		}
	}
}
